/*
 * OpenParts
 * A dynamic-loading components framework for GWT
 * Copyright (C) 2011 Christophe Bouthier  [chris{AT}binary-gastronome{DOT}fr]
 *
 * This work is partially based on work I have done at INRIA (http://www.inria.fr) 
 * in the context of the Qualipso European Project (http://qualipso.org/),
 * The work done at INRIA is Copyright (C) 2006-2011 INRIA
 *
 * This work is distributed under the LGPL version 3
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version 3
 * as published by the Free Software Foundation. See the GNU
 * Lesser General Public License in LGPL.txt for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package fr.openparts.OpenParts.test.gwt.tests;

import com.google.gwt.junit.client.GWTTestCase;

import fr.openparts.OpenParts.client.OPParams;
import fr.openparts.OpenParts.client.OPParamsJS;

/**
 * GWT tests for OPParamsJS/OPParams conversions.
 * 
 * @author Christophe Bouthier [chris{AT}binary-gastronome{DOT}fr]
 * @creation.date 01 January 2010
 */
public class OPParamsJSTestGwt extends GWTTestCase {

    private static final String PARAM_NAME_1 = "name1";
    private static final String PARAM_NAME_2 = "name2";
    private static final String PARAM_VALUE_1 = "value1";
    private static final String PARAM_VALUE_2 = "value2";

    /**
     * Return the name of the tested GWT Module.
     * 
     * @see com.google.gwt.junit.client.GWTTestCase#getModuleName()
     */
    @Override
    public final String getModuleName() {
        return "fr.openparts.OpenParts.test.gwt.TestOpenParts";
    }

    /**
     * Test creating an OPParams object from an OPParamsJS one. Should get the same params inside.
     */
    public final void testCreatingOPParamsFromOPParamsJS() {
        final OPParamsJS pJS = paramsJsFactory(PARAM_NAME_1, PARAM_VALUE_1, PARAM_NAME_2, PARAM_VALUE_2);
        final OPParams p = pJS.toOPParams();
        assertNotNull(p);
        assertEquals("There should be 2 parameters", 2, p.size());
        assertEquals("value of param name1 should be value1", PARAM_VALUE_1, p.getParamValue(PARAM_NAME_1));
        assertEquals("value of param name2 should be value2", PARAM_VALUE_2, p.getParamValue(PARAM_NAME_2));
    }

    /**
     * Test creating an OPParamsJS object from an OPParams one. Should get something not null.
     */
    public final void testCreatingOPParamsJSFromOPParams() {
        final OPParams params = new OPParams(PARAM_NAME_1, PARAM_VALUE_1, PARAM_NAME_2, PARAM_VALUE_2);
        final OPParamsJS paramsJS = OPParamsJS.buildFromOPParams(params);
        assertNotNull("paramsJS shouldn't be null", paramsJS);
        assertEquals("value of param name1 should be value1", PARAM_VALUE_1, paramsJS.getParamValue(PARAM_NAME_1));
        assertEquals("value of param name2 should be value2", PARAM_VALUE_2, paramsJS.getParamValue(PARAM_NAME_2));
    }

    /**
     * Test creating an OPParamsJS object from an null OPParams one. Should raise an assertion error.
     */
    public final void testCreatingOPParamsJSFromNullOPParams() {
        if (assertionsAreEnabled()) {
            try {
                OPParamsJS.buildFromOPParams(null);
                fail("OPParamsJS should raise an assertion error when asking for a param with a null name");
            } catch (AssertionError e) {
                assertTrue("Error should be an AssertionError", e instanceof AssertionError);
            }
        }
    }

    /**
     * Test transit transform OPParams to OPParamsJS and back. Should get everything back.
     */
    public final void testTransitTransform() {
        final OPParams params = new OPParams(PARAM_NAME_1, PARAM_VALUE_1, PARAM_NAME_2, PARAM_VALUE_2);
        final OPParamsJS paramsJS = OPParamsJS.buildFromOPParams(params);
        final OPParams params2 = paramsJS.toOPParams();
        assertNotNull(params2);
        assertEquals("There should be 2 parameters", 2, params2.size());
        assertEquals("value of param name1 should be value1", PARAM_VALUE_1, params2.getParamValue(PARAM_NAME_1));
        assertEquals("value of param name2 should be value2", PARAM_VALUE_2, params2.getParamValue(PARAM_NAME_2));
    }

    /**
     * Test creating an OPParams object from an OPParamsJS one with a null param value. Should raise an assertion error.
     */
    public final void testCreatingOPParamsFromOPParamsJSWithNullParamValue() {
        if (assertionsAreEnabled()) {
            try {
                final OPParamsJS pJS = paramsJsFactory(PARAM_NAME_1, null, PARAM_NAME_2, PARAM_VALUE_2);
                pJS.toOPParams();
                fail("OPParamsJS should raise an assertion error when creating an OPParams from an OPParamsJS with a param with a null value");
            } catch (AssertionError e) {
                assertTrue("Error should be an AssertionError", e instanceof AssertionError);
            }
        }
    }

    /**
     * Test creating an OPParams object from an OPParamsJS one with a empty param value. Should get back the empty value.
     */
    public final void testCreatingOPParamsFromOPParamsJSWithEmptyParamValue() {
        final OPParamsJS pJS = paramsJsFactory(PARAM_NAME_1, "", PARAM_NAME_2, PARAM_VALUE_2);
        final OPParams p = pJS.toOPParams();
        assertNotNull(p);
        assertEquals("There should be 2 parameters", 2, p.size());
        assertEquals("value of param name1 should be an empty string", "", p.getParamValue(PARAM_NAME_1));
        assertEquals("value of param name2 should be value2", PARAM_VALUE_2, p.getParamValue(PARAM_NAME_2));
    }

    /**
     * Test creating an OPParamsJS object from an OPParams one with an empty param value. Should get back the empty value.
     */
    public final void testCreatingOPParamsJSFromOPParamsWidthEmptyParamValue() {
        final OPParams params = new OPParams(PARAM_NAME_1, "", PARAM_NAME_2, PARAM_VALUE_2);
        final OPParamsJS paramsJS = OPParamsJS.buildFromOPParams(params);
        assertNotNull("paramsJS shouldn't be null", paramsJS);
        assertEquals("value of param name1 should be an empty string", "", paramsJS.getParamValue(PARAM_NAME_1));
        assertEquals("value of param name2 should be value2", PARAM_VALUE_2, paramsJS.getParamValue(PARAM_NAME_2));
    }

    /**
     * Test getting description of a OPParamsJS with one param.
     */
    public final void testDescriptionOneParam() {
        final OPParams params = new OPParams(PARAM_NAME_1, PARAM_VALUE_1);
        final OPParamsJS paramsJS = OPParamsJS.buildFromOPParams(params);
        final String description = paramsJS.getDescription();
        assertNotNull("description shouldn't be null", description);
        assertEquals("description should contains only one param and no comma", "[(name1:value1)]", description);
    }
    
    /**
     * Test getting description of a OPParamsJS with two params.
     */
    public final void testDescriptionTwoParams() {
        final OPParams params = new OPParams(PARAM_NAME_1, PARAM_VALUE_1, PARAM_NAME_2, PARAM_VALUE_2);
        final OPParamsJS paramsJS = OPParamsJS.buildFromOPParams(params);
        final String description = paramsJS.getDescription();
        assertNotNull("description shouldn't be null", description);
        assertEquals("description should contains two params separated by a comma", "[(name1:value1), (name2:value2)]", description);
    }
    
    /**
     * Test getting description of an empty OPParamsJS.
     */
    public final void testDescriptionEmptyParam() {
        final OPParams params = new OPParams();
        final OPParamsJS paramsJS = OPParamsJS.buildFromOPParams(params);
        final String description = paramsJS.getDescription();
        assertNotNull("description shouldn't be null", description);
        assertEquals("description should contains no param and no comma", "[]", description);
    }
    
    /**
     * Helper method returning directly an OPParamsJS object (instead of creating one from an OPParams one, as it should be the case).
     * 
     * @param name1
     *            first param name
     * @param value1
     *            first param value
     * @param name2
     *            second param name
     * @param value2
     *            second param value
     * @return an OPParamsJS object.
     */
    private final native OPParamsJS paramsJsFactory(final String name1, final String value1, final String name2, final String value2) /*-{
        var paramsJS = {};
        paramsJS[name1] = value1;
        paramsJS[name2] = value2;
        return paramsJS;
    }-*/;

    /**
     * Check if assertions are enabled.
     * 
     * @return true if assertions are enabled, false otherwise
     */
    private final boolean assertionsAreEnabled() {
        try {
            assert false;
            return false;
        } catch (AssertionError e) {
            return true;
        }
    }
}
